package com.david.mydemo.util;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.google.common.collect.Maps;
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cglib.beans.BeanGenerator;
import org.springframework.cglib.beans.BeanMap;

import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

public class ReflectUtil {

    private static Logger logger = LoggerFactory.getLogger(ReflectUtil.class);

    public static Object getTarget(Object dest, Map<String, Object> addProperties) {
        PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean();
        PropertyDescriptor[] descriptors = propertyUtilsBean.getPropertyDescriptors(dest);
        Map<String, Class> propertyMap = Maps.newHashMap();
        for (PropertyDescriptor d : descriptors) {
            if (!"class".equalsIgnoreCase(d.getName())) {
                propertyMap.put(d.getName(), d.getPropertyType());
            }
        }
        addProperties.forEach((k, v) -> {
            if (v == null) {
                propertyMap.put(k, String.class);
            } else {
                String sclass = v.getClass().toString();
                if (sclass.equals("class java.util.Date")) {//对日期进行处理
                    propertyMap.put(k, Long.class);
                } else {
                    propertyMap.put(k, v.getClass());
                }
            }
        });
        DynamicBean dynamicBean = new DynamicBean(dest.getClass(), propertyMap);
        propertyMap.forEach((k, v) -> {
            try {
                if (!addProperties.containsKey(k)) {
                    dynamicBean.setValue(k, propertyUtilsBean.getNestedProperty(dest, k));
                }
            } catch (Exception e) {
                logger.error("动态添加字段出错", e);
            }
        });
        addProperties.forEach((k, v) -> {
            try {
                if (v == null) {
                    dynamicBean.setValue(k, "");
                } else {
                    String sclass = v.getClass().toString();
                    if (sclass.equals("class java.util.Date")) {//动态添加的字段为date类型需要进行处理
                        Date date = (Date) v;
                        dynamicBean.setValue(k, date.getTime());
                    } else {
                        dynamicBean.setValue(k, v);
                    }
                }
            } catch (Exception e) {
                logger.error("动态添加字段值出错", e);
            }
        });
        Object obj = dynamicBean.getTarget();
        return obj;
    }

    private static class DynamicBean{
        /**
         * 目标对象
         */
        private Object target;
        /**
         * 属性集合
         */
        private BeanMap beanMap;

        public DynamicBean(Class<?> superclass, Map<String, Class> propertyMap) {
            this.target = generateBean(superclass, propertyMap);
            this.beanMap = BeanMap.create(this.target);
        }
        public void setValue(String property, Object value) {
            beanMap.put(property, value);
        }
        public Object getValue(String property) {
            return beanMap.get(property);
        }
        public Object getTarget() {
            return this.target;
        }
        /**
         * 根据属性生成对象
         *
         */
        private Object generateBean(Class superclass, Map<String, Class> propertyMap) {
            BeanGenerator generator = new BeanGenerator();
            if (null != superclass) {
                generator.setSuperclass(superclass);
            }
            BeanGenerator.addProperties(generator, propertyMap);
            return generator.create();
        }
    }

    public static void main(String[] str){
        DemoBean demoBean = new DemoBean();
        demoBean.setCode("123");
        demoBean.setName("测试");
        Map<String, Object> pops = new HashMap<>();
        pops.put("STT_TEXT", "123");
        pops.put("ST_TEXT_TEXT", "123");
        pops.put("S_TEXT", "123");
        Object obj = ReflectUtil.getTarget(demoBean, pops);
        System.out.println(JSONObject.toJSONString(obj, SerializerFeature.WriteMapNullValue));
    }

    public static class DemoBean implements Serializable {
        private static final long serialVersionUID = 1L;
        private String code;
        private String name;

        public String getCode() {
            return code;
        }

        public void setCode(String code) {
            this.code = code;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

    }

}
